#!/bin/bash
#使用说明，用来提示输入参数
clear
echo " "
echo "★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★"
echo "欢迎使用java部署工具，本工具可以用来部署jar包"
echo "作者：王老实"
echo "邮箱：custer7572@163.com"
echo "地址：https://gitee.com/wang-laoshi"
echo "★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★"
echo " "
usage() {
  echo " "
  echo "======================================================================================="
  echo "使用方法如下："
  echo "1.启动jar服务：sh jardeploy.sh start /root/a.jar"
  echo "2.停止jar服务：sh jardeploy.sh stop /root/a.jar"
  echo "3.重启jar服务：sh jardeploy.sh restart /root/a.jar"
  echo "4.查看运行状态：sh jardeploy.sh status /root/a.jar"
  echo "5.启动jar服务并检测启动状态: sh jardeploy.sh start /root/a.jar http://127.0.0.1:8080/check"
  echo "6.启动jar服务并设置启动参数: sh jardeploy.sh start /root/a.jar http://127.0.0.1:8080/check -Xms256m -Xmx512m -XX:+UseG1GC -server"
  echo "7:部署tgz包：sh jardeploy.sh deploytgz /root/a.tgz http://127.0.0.1:8080/check -Xms256m -Xmx512m -XX:+UseG1GC -server"
  echo "8:部署jar包：sh jardeploy.sh deployjar /root/a.jar http://127.0.0.1:8080/check -Xms256m -Xmx512m -XX:+UseG1GC -server"
  echo "9:回滚jar包：sh jardeploy.sh rollback /root/a.jar http://127.0.0.1:8080/check -Xms256m -Xmx512m -XX:+UseG1GC -server"
  echo "======================================================================================="
  echo "参数含义"
  echo "1:start/stop/restart/status/deploytgz/deployjar/rollback: 执行动作"
  echo "2:/root/a.jar /root/a.tgz：待部署文件绝对路径"
  echo "3:http://127.0.0.1:8080/check: 检查是否启动的url，如果返回200则说明启动成功"
  echo "4:-Xms256m -Xmx512m -XX:+UseG1GC -server:JVM启动参数，可按照程序自定义参数"
  echo "5:执行动作和文件路径为必选参数，其他为可选参数"
  echo "======================================================================================="
  echo " "
  echo " "
  exit 1
}
PARAM_NUM=$#
if [ ${PARAM_NUM} -lt 2 ]; then
  echo 'T_T,,,输入错误,缺少命令参数，至少需要2个参数...'
  usage
fi
JAVA_VERSION=$(java -version 2>&1 | sed '1!d' | sed -e 's/"//g' | awk '{print $3}')
echo "Java版本:$JAVA_VERSION"
ACTION=$1    #操作（start stop restart status）
FILENAME=$2  #目标文件，可以(.jar .tgz)
CHECKURL=$3  #检查是否启动的url
JVM_PARAM="" #java启动参数
#启动参数拼接
if [ ${PARAM_NUM} -gt 3 ]; then
  param_idx=0
  for i in "$@"; do
    echo $i $param_idx $JVM_PARAM
    if [ $param_idx -gt 2 ]; then
      JVM_PARAM="$JVM_PARAM $i"
    fi
  done
fi
JAR_FILE=""                     #jar文件全路径
JAR_FILE_BK=""                  #jar文件备份全路径
JAR_FILE_LOG=""                 #jar程序去启动后本地日志路径
JAR_FILE_NAME=""                #jar文件名，用于杀死进程使用
WORK_DIR=$(dirname "$FILENAME") #工作空间
cd "$WORK_DIR"                  #切换到工作空间目录下
#检查程序是否在运行

check_file() {
  if [ ! -s "$FILENAME" ]; then
    echo "[$FILENAME]文件不存在,将退出程序"
    exit 1
  fi
}

#当action in (start,stop,status,restart)时调用，设置第二个参数=JAR_FILE
init_jar() {
  JAR_FILE=$FILENAME
  JAR_FILE_NAME=${JAR_FILE##*/}
  JAR_FILE_BK=$JAR_FILE.bk
  JAR_FILE_LOG=${JAR_FILE/.jar/.log}
  echo "init_jar,JAR_FILE=$JAR_FILE ,JAR_FILE_NAME=$JAR_FILE_NAME"
}

#当action = deploytgz时调用,将.tgz的值替换为.jar
init_tgz() {
  JAR_FILE_NAME=$(tar -tf "$FILENAME")
  JAR_FILE="$WORK_DIR"/"$JAR_FILE_NAME"
  JAR_FILE_BK=$JAR_FILE.bk
  JAR_FILE_LOG=${JAR_FILE/.jar/.log}
  echo "init_tgz,JAR_FILE=$JAR_FILE ,JAR_FILE_NAME=$JAR_FILE_NAME"
}

#解压缩
unzip() {
  if [ -s "$FILENAME" ]; then
    echo "开始解压缩[$FILENAME]"
    tar zxvf "$FILENAME" -C "$WORK_DIR"
  else
    echo "$FILENAME不存在，请检查"
    exit 1
  fi
}

is_exist() {
  pid=$(jps -l | grep "$JAR_FILE_NAME" | grep -v grep | awk '{print $1}')
  #如果不存在返回1，存在返回0
  if [ -z "${pid}" ]; then
    echo "[$JAR_FILE]尚未启动"
    return 1
  else
    echo "[$JAR_FILE]已经启动,pid=[$pid]"
    return 0
  fi
}

#备份jar文件
backjarfile() {
  cp "$JAR_FILE" "$JAR_FILE_BK"
  echo "备份到[${JAR_FILE_BK}]成功"
}

#还原jar文件
rollbackjarfile() {
  cp "$JAR_FILE_BK" "$JAR_FILE"
  echo "还原到[${JAR_FILE_BK}]成功"
}

#启动方法
start() {
  is_exist
  if [ $? -eq 0 ]; then
    echo "[${JAR_FILE}]已经在运行 .pid=[${pid}],如果要重新启动，请输入命令sh jardeploy.sh restart ${JAR_FILE}"
  else
    echo "正在启动java服务[${JAR_FILE}]..."
    java_start_cmd="java -jar ${JAR_FILE} ${JVM_PARAM}"
    echo "$java_start_cmd"
    nohup java -jar "${JAR_FILE}" "${JVM_PARAM}" >"$JAR_FILE_LOG" 2>&1 &
    if [ ${PARAM_NUM} -gt 2 ]; then
      echo "开始执行http服务状态检查...,http检测地址:[${CHECKURL}]"
      start_status=0
      for i in {1..30}; do
        checkstr=$(curl -o /dev/null -s -w "%{http_code}" "${CHECKURL}")
        if [ "${checkstr}" -eq 200 ]; then
          echo "http状态服务检测成功,$JAR_FILE启动完成"
          echo "启动日志参见$JAR_FILE_LOG"
          start_status=1
          break
        else
          echo "http状态服务检测中..."
        fi
        sleep 2
      done
      if [ $start_status -eq 0 ]; then
        echo "http状态服务检测失败,系统未启动"
        echo "错误日志参见$JAR_FILE_LOG"
        exit 1
      fi
    fi
  fi
}

#停止方法
stop() {
  is_exist
  if [ $? -eq 0 ]; then
    echo "停止服务[${JAR_FILE}]中,pid=[$pid]..."
    kill -9 $pid
    sleep 5
    echo "[${JAR_FILE}]已停止"
    echo " "
  else
    echo "检测到[${JAR_FILE}]没有运行,stop操作无需执行"
    echo " "
  fi
}

#输出运行状态
status() {
  is_exist
  if [ $? -eq 0 ]; then
    echo "status操作检测状态,[${JAR_FILE}]运行中... Pid 是 ${pid}"
  else
    echo "status操作检测状态,[${JAR_FILE}]没有运行."
  fi
}

#重启
restart() {
  stop
  start
}

#根据动作，选择执行对应方法，不输入则执行使用说明
case "$ACTION" in
"start")
  check_file
  init_jar
  start
  ;;
"stop")
  check_file
  init_jar
  stop
  ;;
"status")
  check_file
  init_jar
  status
  ;;
"restart")
  check_file
  init_jar
  restart
  ;;
"deploytgz")
  check_file
  init_tgz
  stop
  unzip
  backjarfile
  start
  ;;
"deployjar")
  check_file
  init_jar
  stop
  backjarfile
  start
  ;;
"rollback")
  check_file
  init_jar
  stop
  rollbackjarfile
  start
  ;;
*)
  usage
  ;;
esac
